Skip to content

fix(models/ocr): use OS trust store for model downloads; route polars via lts-cpu wrapper#1175

Open
ksaurabhAparavi wants to merge 1 commit into
rocketride-org:developfrom
ksaurabhAparavi:fix/RR-1162-model-download-tls-and-polars
Open

fix(models/ocr): use OS trust store for model downloads; route polars via lts-cpu wrapper#1175
ksaurabhAparavi wants to merge 1 commit into
rocketride-org:developfrom
ksaurabhAparavi:fix/RR-1162-model-download-tls-and-polars

Conversation

@ksaurabhAparavi

@ksaurabhAparavi ksaurabhAparavi commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • SSL: install truststore and inject it into the default SSL context so HTTPS model downloads use the full OS trust store — fixes "unable to get local issuer certificate" behind TLS-intercepting proxies (falls back to certifi).
  • polars: route OCR polars imports through ai.common.polars, which installs polars-lts-cpu and removes any transitively-pulled plain polars, fixing SIGILL / SEH 0xc000001d on x86_64 hosts without AVX2/FMA.

Testing

  • CI (./builder test) — relying on GitHub Actions; not runnable in the contributor's local shell (engine build / Maven / torch unavailable). Static checks (compile, no conflict markers) pass.

Linked Issue

Fixes #1162

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds import-time fixes: an SSL trust-store patcher used by the model loader and a polars-lts-cpu wrapper used by the OCR node, plus platform-conditional requirements to ensure correct binaries are installed on x86_64 hosts.

Changes

TLS/SSL and Polars LTS CPU Runtime Robustness

Layer / File(s) Summary
SSL/TLS trust store patching infrastructure
packages/ai/src/ai/common/ssl/__init__.py, packages/ai/src/ai/common/ssl/requirements.txt, packages/ai/src/ai/common/models/__init__.py
Creates ai.common.ssl that installs truststore, attempts truststore.inject_into_ssl() on import, falls back to certifi env var setup if needed, and wires an early import into the model loader.
Polars LTS CPU wrapper module
packages/ai/src/ai/common/polars/__init__.py, packages/ai/src/ai/common/polars/requirements.txt
Adds ai.common.polars which enforces polars-lts-cpu on x86_64: installs platform deps, detects/remediates plain polars (uninstall/reinstall), clears sys.modules, re-imports polars as pl, and exports pl.
OCR node Polars wrapper integration
nodes/src/nodes/ocr/IGlobal.py, nodes/src/nodes/ocr/requirements.txt
Imports ai.common.polars at module load, changes ModelServerOCR.to_ocr_dataframe to from ai.common.polars import pl, and pins polars-lts-cpu in OCR requirements with a platform marker.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I nudge the sockets, patch the TLS seam,
I swap polars wheels so old CPUs dream,
Before models fetch and OCR runs free,
Two small imports set the runtime key. 🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed All coding objectives from #1162 are met: TLS verification routed through OS trust store with certifi fallback, and polars-lts-cpu enforced via ai.common.polars wrapper on x86_64.
Out of Scope Changes check ✅ Passed All changes directly address #1162 objectives: SSL/TLS patching, polars dependency management, and OCR routing through the new wrapper.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(models/ocr): use OS trust store for model downloads; route polars via lts-cpu wrapper' directly and accurately describes the main changes: SSL/TLS trust store handling for model downloads and polars routing through lts-cpu wrapper.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ai/src/ai/common/ssl/__init__.py`:
- Around line 41-42: The call to depends(requirements) is executed before the
fallback try/except and can raise during import; move the depends(requirements)
invocation into the existing try block that attempts the truststore installation
so failures are caught by the except and the module can fall back to certifi or
the default SSL context. Specifically, relocate the depends(requirements) call
so it runs inside the same try that wraps truststore installation (referencing
the requirements variable and the truststore installation logic) and do not call
depends at module import level outside that try/except.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: aca16ad0-7964-4b0a-9f1f-ab329687d4fd

📥 Commits

Reviewing files that changed from the base of the PR and between efecb7e and d5c6abc.

📒 Files selected for processing (7)
  • nodes/src/nodes/ocr/IGlobal.py
  • nodes/src/nodes/ocr/requirements.txt
  • packages/ai/src/ai/common/models/__init__.py
  • packages/ai/src/ai/common/polars/__init__.py
  • packages/ai/src/ai/common/polars/requirements.txt
  • packages/ai/src/ai/common/ssl/__init__.py
  • packages/ai/src/ai/common/ssl/requirements.txt

Comment on lines +41 to +42
requirements = os.path.dirname(os.path.realpath(__file__)) + '/requirements.txt'
depends(requirements)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Move depends(requirements) inside the fallback try.

Lines 41-42 can raise before the fallback logic starts, so a failed truststore install aborts ai.common.ssl import entirely instead of degrading to certifi or leaving the default SSL context unchanged. Because packages/ai/src/ai/common/models/__init__.py imports this module eagerly, that turns a transient pip/network failure into a hard failure for every ai.common.models import.

Suggested fix
-requirements = os.path.dirname(os.path.realpath(__file__)) + '/requirements.txt'
-depends(requirements)
-
 try:
+    requirements = os.path.dirname(os.path.realpath(__file__)) + '/requirements.txt'
+    depends(requirements)
     import truststore

     truststore.inject_into_ssl()
 except Exception:

Based on learnings, import-time depends(...) in packages/ai/src/ai/**/__init__.py is intentional; the problem here is only that this call sits outside the graceful-fallback path.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
requirements = os.path.dirname(os.path.realpath(__file__)) + '/requirements.txt'
depends(requirements)
try:
requirements = os.path.dirname(os.path.realpath(__file__)) + '/requirements.txt'
depends(requirements)
import truststore
truststore.inject_into_ssl()
except Exception:
# fallback logic continues here
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai/src/ai/common/ssl/__init__.py` around lines 41 - 42, The call to
depends(requirements) is executed before the fallback try/except and can raise
during import; move the depends(requirements) invocation into the existing try
block that attempts the truststore installation so failures are caught by the
except and the module can fall back to certifi or the default SSL context.
Specifically, relocate the depends(requirements) call so it runs inside the same
try that wraps truststore installation (referencing the requirements variable
and the truststore installation logic) and do not call depends at module import
level outside that try/except.

Source: Learnings

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
🤖 Internal: Discord sync marker

Auto-managed by the Discord notification workflow. Stores the linked Discord message ID. Do not edit or delete.

@github-actions github-actions Bot added module:nodes Python pipeline nodes module:ai AI/ML modules labels Jun 8, 2026
… via lts-cpu wrapper

- ssl: install truststore and inject it into the default SSL context so
  HTTPS model downloads use the full OS trust store, fixing "unable to get
  local issuer certificate" behind TLS-intercepting proxies (falls back to
  certifi).
- polars: route OCR polars imports through ai.common.polars, which installs
  polars-lts-cpu and removes any transitively-pulled plain polars, fixing
  SIGILL / SEH 0xc000001d on x86_64 hosts without AVX2/FMA.

Fixes rocketride-org#1162
@ksaurabhAparavi ksaurabhAparavi force-pushed the fix/RR-1162-model-download-tls-and-polars branch from d5c6abc to a940903 Compare June 8, 2026 11:51
@ksaurabhAparavi ksaurabhAparavi changed the title fix(models/OCR): use OS trust store for HTTPS model downloads and route polars through ai.common.polars wrapper (#29) fix(models/ocr): use OS trust store for model downloads; route polars via lts-cpu wrapper Jun 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ai/src/ai/common/polars/__init__.py`:
- Around line 51-77: The current x86_64 remediation block (guarded by
_NEEDS_LTS) swallows all exceptions and ignores pip(...) return values, so
uninstall/install failures can leave an incompatible polars present; change the
cleanup to fail fast: after each pip('uninstall'...) and pip('install'...) call
in the remediation branch, check the boolean return and if False raise a clear
RuntimeError (or re-raise the underlying exception) so the import fails fast;
also avoid the blanket except Exception: pass — either remove it or re-raise
after logging so failures in the remediation (within the try around
importlib.metadata, pip calls, or sys.modules manipulations) surface immediately
and prevent a silent fallback to an incompatible polars.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bb20251c-e4ff-4c05-ab8f-d24ec4be900a

📥 Commits

Reviewing files that changed from the base of the PR and between d5c6abc and a940903.

📒 Files selected for processing (7)
  • nodes/src/nodes/ocr/IGlobal.py
  • nodes/src/nodes/ocr/requirements.txt
  • packages/ai/src/ai/common/models/__init__.py
  • packages/ai/src/ai/common/polars/__init__.py
  • packages/ai/src/ai/common/polars/requirements.txt
  • packages/ai/src/ai/common/ssl/__init__.py
  • packages/ai/src/ai/common/ssl/requirements.txt

Comment on lines +51 to +77
if _NEEDS_LTS:
try:
import importlib.metadata as _md

_has_plain_polars = False
try:
_md.version('polars')
_has_plain_polars = True
except _md.PackageNotFoundError:
# Plain `polars` not installed — only polars-lts-cpu is on disk,
# which is exactly the desired state. No cleanup needed.
pass

if _has_plain_polars:
# Plain `polars` was pulled in transitively (img2table etc.).
# Drop it and force-reinstall lts-cpu so its binary wins on disk.
pip('uninstall', '-y', 'polars')
pip('install', '--force-reinstall', '--no-deps', 'polars-lts-cpu')

# Drop any already-loaded polars modules so the next import
# picks up the freshly-written files instead of cached state.
for _mod in [m for m in list(sys.modules) if m == 'polars' or m.startswith('polars.')]:
sys.modules.pop(_mod, None)
except Exception:
# Best-effort cleanup. If it fails, the import below will surface
# the underlying issue with a real traceback.
pass

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast when polars remediation does not succeed.

The x86_64 remediation path treats uninstall/reinstall as best-effort and swallows failures. Because pip(...) returns a boolean, a failed cleanup can silently leave incompatible polars active, which reintroduces the crash class this module is meant to prevent.

Suggested fix
 if _NEEDS_LTS:
     try:
         import importlib.metadata as _md
@@
         if _has_plain_polars:
@@
-            pip('uninstall', '-y', 'polars')
-            pip('install', '--force-reinstall', '--no-deps', 'polars-lts-cpu')
+            uninstalled = pip('uninstall', '-y', 'polars')
+            installed = pip('install', '--force-reinstall', '--no-deps', 'polars-lts-cpu')
+            if not (uninstalled and installed):
+                raise RuntimeError('Failed to enforce polars-lts-cpu on x86_64 host')
@@
-    except Exception:
-        # Best-effort cleanup. If it fails, the import below will surface
-        # the underlying issue with a real traceback.
-        pass
+    except Exception as exc:
+        raise RuntimeError('Polars runtime remediation failed before import') from exc
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if _NEEDS_LTS:
try:
import importlib.metadata as _md
_has_plain_polars = False
try:
_md.version('polars')
_has_plain_polars = True
except _md.PackageNotFoundError:
# Plain `polars` not installed — only polars-lts-cpu is on disk,
# which is exactly the desired state. No cleanup needed.
pass
if _has_plain_polars:
# Plain `polars` was pulled in transitively (img2table etc.).
# Drop it and force-reinstall lts-cpu so its binary wins on disk.
pip('uninstall', '-y', 'polars')
pip('install', '--force-reinstall', '--no-deps', 'polars-lts-cpu')
# Drop any already-loaded polars modules so the next import
# picks up the freshly-written files instead of cached state.
for _mod in [m for m in list(sys.modules) if m == 'polars' or m.startswith('polars.')]:
sys.modules.pop(_mod, None)
except Exception:
# Best-effort cleanup. If it fails, the import below will surface
# the underlying issue with a real traceback.
pass
if _NEEDS_LTS:
try:
import importlib.metadata as _md
_has_plain_polars = False
try:
_md.version('polars')
_has_plain_polars = True
except _md.PackageNotFoundError:
# Plain `polars` not installed — only polars-lts-cpu is on disk,
# which is exactly the desired state. No cleanup needed.
pass
if _has_plain_polars:
# Plain `polars` was pulled in transitively (img2table etc.).
# Drop it and force-reinstall lts-cpu so its binary wins on disk.
uninstalled = pip('uninstall', '-y', 'polars')
installed = pip('install', '--force-reinstall', '--no-deps', 'polars-lts-cpu')
if not (uninstalled and installed):
raise RuntimeError('Failed to enforce polars-lts-cpu on x86_64 host')
# Drop any already-loaded polars modules so the next import
# picks up the freshly-written files instead of cached state.
for _mod in [m for m in list(sys.modules) if m == 'polars' or m.startswith('polars.')]:
sys.modules.pop(_mod, None)
except Exception as exc:
raise RuntimeError('Polars runtime remediation failed before import') from exc
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai/src/ai/common/polars/__init__.py` around lines 51 - 77, The
current x86_64 remediation block (guarded by _NEEDS_LTS) swallows all exceptions
and ignores pip(...) return values, so uninstall/install failures can leave an
incompatible polars present; change the cleanup to fail fast: after each
pip('uninstall'...) and pip('install'...) call in the remediation branch, check
the boolean return and if False raise a clear RuntimeError (or re-raise the
underlying exception) so the import fails fast; also avoid the blanket except
Exception: pass — either remove it or re-raise after logging so failures in the
remediation (within the try around importlib.metadata, pip calls, or sys.modules
manipulations) surface immediately and prevent a silent fallback to an
incompatible polars.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

module:ai AI/ML modules module:nodes Python pipeline nodes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Model downloads fail behind corporate TLS proxies; polars AVX2 crash on older CPUs

1 participant